﻿#pragma once
/**@brief W意波 编写*/
namespace LK
{
	/**
	@brief 用以进行通用的转换
	@note 可以通过特化Convert类来实现模板通用转换过程*/
	template<class to, class from>struct Convert
	{
		/**
		@brief 从from转换到to*/
		static inline to From(from f) { return to(f); }
		/**
		@brief 重新解释*/
		static inline typename AddLValueReference<typename RemoveConst<to>::T>::T
			RefFrom(typename AddLValueReference<typename AddConst<from>::T>::T f)
		{
			return reinterpret_cast<typename AddLValueReference<typename RemoveConst<to>::T>::T>
				(const_cast<typename AddLValueReference<typename RemoveConst<from>::T>::T>(f));
		}
	};
	/**
	@brief 部分专用化版本1：从未知类型对象指针进行的转换*/
	template<class to>struct Convert<to, void>
	{
		/**
		@brief 直接抛出异常*/
		static inline to From(...) { Throw<PException >(L"非法转换"); }
		/**
		@brief 直接抛出异常*/
		static inline typename AddLValueReference<typename RemoveConst<to>::T>::T RefFrom(...) { Throw<PException >(L"非法转换"); }
		/**
		@brief 从未知数据类型的封装数据指针进行转换*/
		static inline typename UseT<IsFunction<to>::V || IsArray<to>::V, to, typename AddLValueReference<to>::T>::T FromDataPtr(void*p)
		{
			if (IsArray<typename RemoveReference<to>::T>::V || IsLValueReference<to>::V || IsSame<void, typename ArgT<1, typename IsFunction<typename UseT<IsFunction<to>::V, void(ptr<Object>::*)(), to>::T>::T>::T>::V)
				return **(typename AddPointer<typename AddPointer<to>::T>::T)p;
			return **(typename AddPointer<typename AddPointer<to>::T>::T)&p;
		}
		/**
		@brief 从未知数据类型的对象指针进行构造*/
		static inline typename UseT<IsFunction<to>::V || IsArray<to>::V, to, typename AddLValueReference<to>::T>::T FromObjectPtr(void*p)
		{
			return **(typename AddPointer<typename AddPointer<to>::T>::T)&p;
		}
	};
	/**
	@brief 部分专用化版本2：转换到数据类型*/
	template<class from>struct Convert<void, from>
	{
		/**
		@brief 不做操作*/
		static inline void From(...) { }
		/**
		@brief 不做操作*/
		static inline void RefFrom(...) {}
		/**
		@brief 封箱数据类型，进行如下顺序判断后划分：
		1.托管类型保存句柄(偏特化版本实现)
		2.函数类型或函数指针类型保存函数指针
		3.左值引用类型或者数组类型保存指针
		4.右值引用类型保存副本
		5.其它保存副本*/
		typedef
			typename UseT<(IsFunction<typename RemoveAllExtents<from>::T>::V && 0 == (IsFunction<typename RemoveAllExtents<from>::T>::type&(TypeExtents::Thiscall + TypeExtents::ThiscallConst)))
			|| IsLValueReference<from>::V || IsArray<from>::V,
			typename RemoveAllExtents <from>::T,//副本类型
			typename AddPointer<from>::T>::T//指针
			DataType;//结果数据类型
					 /**
					 @brief 函数或数组或左值引用构造方法:取指针*/
		template<class TT>static typename UseIf<(IsFunction<typename RemoveAllExtents<TT>::T>::V && 0 == (IsFunction<typename RemoveAllExtents<TT>::T>::type&(TypeExtents::Thiscall + TypeExtents::ThiscallConst))) || IsArray<TT>::V || IsLValueReference<TT>::V, DataType>::T
			_ToData(typename AddConst<typename AddLValueReference<TT>::T>::T t)
		{
			return (DataType)&t;
		}
		/**
		@brief 非函数和数组构造方法:复制*/
		template<class TT>static typename UseIf<!((IsFunction<typename RemoveAllExtents<TT>::T>::V && 0 == (IsFunction<typename RemoveAllExtents<TT>::T>::type&(TypeExtents::Thiscall + TypeExtents::ThiscallConst))) || IsArray<TT>::V || IsLValueReference<TT>::V), DataType>::T
			_ToData(typename AddConst<typename AddLValueReference<TT>::T>::T t, void*p = NULL)
		{
			return (DataType)t;
		}
		/**
		@brief 间接取取指针*/
		template<class TT>static typename UseIf<(IsFunction<typename RemoveAllExtents<TT>::T>::V && 0 == (IsFunction<typename RemoveAllExtents<TT>::T>::type&(TypeExtents::Thiscall + TypeExtents::ThiscallConst))) || IsArray<TT>::V || IsLValueReference<TT>::V, void*>::T
			_ToDataPtr(typename AddConst<typename AddLValueReference<TT>::T>::T t)
		{
			DataType d = _ToData<TT>(t);
			return *(void**)&d;
		}
		/**
		@brief 直接取指针*/
		template<class TT>static typename UseIf<!((IsFunction<typename RemoveAllExtents<TT>::T>::V && 0 == (IsFunction<typename RemoveAllExtents<TT>::T>::type&(TypeExtents::Thiscall + TypeExtents::ThiscallConst))) || IsArray<TT>::V || IsLValueReference<TT>::V), void*>::T
			_ToDataPtr(typename AddConst<typename AddLValueReference<TT>::T>::T t)
		{
			return (void*)&t;
		}
		static inline DataType ToDataFrom(typename AddConst<typename AddLValueReference<from>::T>::T t) { return _ToData<from>(t); }
		static inline void* ToDataPtrFrom(typename AddConst<typename AddLValueReference<from>::T>::T t) { return _ToDataPtr<from>(t); }
		static inline void WriteDataFrom(void*p, typename AddConst<typename AddLValueReference<from>::T>::T t) { *(DataType*)p = _ToData<from>(t); }
		static inline void* ToObjectPtrFrom(typename AddConst<typename AddLValueReference<from>::T>::T t) { return Convert<void*,typename AddPointer<from>::T >::RefFrom((typename AddPointer<from>::T)&t); }
	};
#ifdef _CLR
	template<class to>struct Convert<to^, void>
	{
		static inline to^ FromDataPtr(void*p) { return *(gcroot<to^>*)p; }
		static inline to^ FromObjectPtr(void*p) { gcroot<to^>t((gcroot<to^>&)p); ((gcroot<to^>&)p).~gcroot<to^>(); return t; }
	};
	template<class from>struct Convert<void, from^>
	{
		static gcroot<from^> ToDataFrom(from^f) { return f; }
		static inline void WriteDataFrom(void*p, from^f) { *(gcroot<from^>*)p = f; }
		static inline void* ToObjectPtrFrom(from^ t) { void* val; placementnew((gcroot<from^>*)&val,t); return val; }
	};
	template<class to>struct Convert<to^%, void>
	{
		static inline to^% FromDataPtr(void*p) { return *(to^*)p; }
		static inline to^% FromObjectPtr(void*p) { return *(to^*)p; }
	};
	template<class from>struct Convert<void, from^%>
	{
		static from^* ToDataFrom(from^const%f){
			pin_ptr<from^const>ptr = &f; return (from^*)(from^const*)ptr;
		}
		static inline void WriteDataFrom(void*p, from^%f){
			pin_ptr<from^>ptr = &f;
			*(from^**)p = (from^*)ptr;
		}
		static inline void* ToObjectPtrFrom(from^ t) { return (void*)ToDataFrom(from^const%f); }
	};
#endif
	/**
	@brief 部分专用化版本3：未知类型之间不进行转换*/
	template<>struct Convert<void, void>
	{
		typedef void* DataType;
		static inline void From(...) { }
		static inline void RefFrom(...) {}
		static inline void FromDataPtr(...) {}
		static inline void* ToDataFrom(...) { return NULL; }
		static inline void WriteDataFrom(...) {}
	};
}